package services

import (
	"encoding/json"
	"errors"
	"lingc/models"
	"lingc/utils"
	"log"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// AuthUserService 提供账号登录校验的服务
type AuthUserService struct {
	DB *gorm.DB
}

// NewAuthUserService 创建一个新的 AuthUserService 实例
func NewAuthUserService(db *gorm.DB) *AuthUserService {
	return &AuthUserService{DB: db}
}

// Login 校验账号和密码是否匹配
func (s *AuthUserService) Login(username, password, ip string) (*models.AuthUser, error) {
	var data models.AuthUser
	if err := s.DB.Where("username = ?", username).First(&data).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户名或密码错误")
		}
		return nil, err
	}

	if err := s.ValidatePassword(data.Password, password); err != nil {
		return nil, err
	}
	data.LoginLastIP = ip
	data.LoginNum++
	data.LoginLastAt = time.Now().Unix()
	// log.Printf("用户：%v", data)
	s.DB.Save(&data)
	// log.Printf("用户：%v", data) // 修改日志记录，使用 Printf 以便格式化输出
	return &data, nil
}

// ValidatePassword 校验密码是否匹配
func (s *AuthUserService) ValidatePassword(hashedPassword, password string) error {
	if err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)); err != nil {
		// log.Printf("密码校验失败: %v", err) // 添加日志记录，记录密码校验失败的原因
		return errors.New("用户名或密码错误")
	}
	return nil
}

// GetAuthUserById 获取用户信息
func (s *AuthUserService) GetAuthUserById(data_id uint) (*models.AuthUser, error) {
	var data models.AuthUser
	if err := s.DB.Preload("AuthGroup").First(&data, data_id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("数据不存在")
		}
		return nil, err
	}
	// log.Printf("data_info:%v", data.AuthGroup.ID)
	return &data, nil
}

func (s *AuthUserService) GetAuthRules(ruleIDs []string) ([]models.AuthRule, error) {
	var rule []models.AuthRule
	if err := s.DB.Where("id IN ?", ruleIDs).Select(rule).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("权限不存在")
		}
		return nil, err
	}
	return rule, nil
}

// GetMenusRoutes 获取用户菜单路由
func (s *AuthUserService) GetMenusRouteList(c *gin.Context) ([]models.AuthRuleData, error) {
	var authRules []models.AuthRule
	// 获取语言
	langInterface, ok := c.Get("lang")
	log.Printf("langInterface:%v", langInterface)
	lang := "en"
	if ok {
		lang = langInterface.(string)
	}
	authRulesStr := utils.GetRedis("auth_rule_list" + lang)
	if authRulesStr != "" {
		// 将JSON数据反序列化到map
		authRulesArr := []models.AuthRuleData{}
		err := json.Unmarshal([]byte(authRulesStr), &authRulesArr)
		return authRulesArr, err
	}
	status := 1
	if err := s.DB.Where("status = ?", status).Find(&authRules).Error; err != nil {
		return nil, err
	}
	//循环 authRules
	authRulesArr := []models.AuthRuleData{}
	mapUrlArr := make(map[string]models.AuthRuleMenusName)
	mapPid := make(map[int]string)
	for _, rule := range authRules {
		log.Printf("rule:%s---%s", rule.Title, lang)
		item := models.AuthRuleData{
			ID:       rule.ID,
			Name:     rule.Name,
			Title:    Translate(rule.Title, lang),
			Type:     rule.Type,
			Icon:     rule.Icon,
			URL:      rule.URL,
			URLParam: rule.URLParam,
			Rank:     rule.Rank,
			ParentID: rule.ParentID,
		}
		mapPid[int(rule.ID)] = utils.GenerateMD5(strings.ToLower(rule.Name))
		authRulesArr = append(authRulesArr, item)
		mapUrlArr[utils.GenerateMD5(strings.ToLower(rule.Name))] = models.AuthRuleMenusName{
			ID:       rule.ID,
			ParentID: rule.ParentID,
			Title:    rule.Title,
		}
	}

	jsonData, err := json.Marshal(authRulesArr)
	if err != nil {
		return nil, err
	}
	// log.Printf("mapUrlArr:%s", mapUrlArr)
	mapData, err := json.Marshal(mapUrlArr)
	if err != nil {
		return nil, err
	}
	// log.Printf("mapData:%s", mapData)
	mapPidData, err := json.Marshal(mapPid)
	if err != nil {
		return nil, err
	}
	// log.Printf("jsonData:%s", jsonData)
	utils.SetRedis("auth_rule_list"+lang, jsonData, 24*60)
	utils.SetRedis("auth_rule_map_url", mapData, 24*60)
	utils.SetRedis("auth_rule_map_pid", mapPidData, 26*60)

	return authRulesArr, nil
}

//表单业务

/**
 * @Description: 分页获取用户列表
 * @param where
 * @param page
 * @param pageSize
 * @param fields
 * @return []*models.AuthUser
 * @return int
 * @return int64
 * @return error
 */
func (s *AuthUserService) PageAuthUserList(where string, page, pageSize int) ([]*models.AuthUserList, int, int64, error) {
	var datas []*models.AuthUser
	var total int64

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 获取总记录数
	if err := s.DB.Model(&models.AuthUser{}).Where(where).Count(&total).Error; err != nil {
		return nil, 1, 0, err
	}
	// 获取分页数据
	if err := s.DB.Where(where).Preload("AuthGroup").Offset(offset).Limit(pageSize).Order("id DESC").Find(&datas).Error; err != nil {
		return nil, 1, 0, err
	}
	var list []*models.AuthUserList
	list = []*models.AuthUserList{}
	for _, data := range datas {
		title := data.AuthGroup.Title
		if data.AuthGroup.Title == "" {
			title = "超级管理员"
		}
		list = append(list, &models.AuthUserList{
			ID:          data.ID,
			Username:    data.Username,
			Realname:    data.Realname,
			Avatar:      data.Avatar,
			Status:      data.Status,
			GroupName:   title,
			GroupID:     data.GroupID,
			LoginNum:    data.LoginNum,
			LoginLastIP: data.LoginLastIP,
			LoginLastAt: time.Unix(data.LoginLastAt, 0).Format("2006-01-02 15:04:05"), // 格式化时间戳
			CreatedAt:   time.Unix(data.CreatedAt, 0).Format("2006-01-02 15:04:05"),   // 格式化时间戳
			UpdatedAt:   time.Unix(data.UpdatedAt, 0).Format("2006-01-02 15:04:05"),   // 格式化时间戳
		})
	}
	return list, page, total, nil
}

/**
 * @Description: 创建新用户
 * @param username
 * @param password
 * @param realname
 * @param avatar
 * @param status
 * @return *models.AuthUserCreate
 * @return error
 */
func (s *AuthUserService) CreateAuthUser(data *models.AuthUserCreate) (*models.AuthUserCreate, error) {
	// 检查用户名是否已存在
	var existingUser models.AuthUser
	if err := s.DB.Where("username = ?", data.Username).First(&existingUser).Error; err == nil {
		return nil, errors.New("用户名已存在")
	}
	addData := &models.AuthUser{
		Username:  data.Username,
		Realname:  data.Realname,
		Status:    data.Status,
		Avatar:    data.Avatar,
		GroupID:   data.GroupID,
		CreatedAt: time.Now().Unix(),
		UpdatedAt: time.Now().Unix(),
	}
	// log.Printf("addUser: %v", addData)
	if data.Password != "" {
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(data.Password), bcrypt.DefaultCost)
		if err != nil {
			return nil, err
		}
		addData.Password = string(hashedPassword)
	}
	// 保存新用户到数据库
	if err := s.DB.Create(addData).Error; err != nil {
		return nil, err
	}
	return data, nil
}

// GetAuthUser 获取用户信息
func (s *AuthUserService) GetAuthUser(where string) (*models.AuthUser, error) {
	var data models.AuthUser
	if err := s.DB.Where(where).Preload("AuthGroup").First(&data).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("数据不存在")
		}
		return nil, err
	}
	// log.Printf("data_info:%v", data.AuthGroup)
	return &data, nil
}

/**
 * @Description: 更新用户信息
 * @param data
 * @return error
 */
func (s *AuthUserService) UpdateAuthUser(data *models.AuthUserUpdate) (*models.AuthUserUpdate, error) {
	// 检查用户名是否已存在
	var existingUser models.AuthUser

	if err := s.DB.Where("id = ?", data.ID).First(&existingUser).Error; err != nil {
		return nil, errors.New("数据不存在")
	}
	existingUser.Username = data.Username
	existingUser.Realname = data.Realname
	existingUser.Avatar = data.Avatar
	existingUser.Status = data.Status
	existingUser.GroupID = data.GroupID
	existingUser.UpdatedAt = time.Now().Unix()

	if data.Password != "" {
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(existingUser.Password), bcrypt.DefaultCost)
		if err != nil {
			return nil, err
		}
		existingUser.Password = string(hashedPassword)
	}
	err := s.DB.Save(existingUser).Error
	if err != nil {
		return nil, errors.New("更新失败")
	}
	return data, err
}

/**
 * @Description: 删除用户
 * @param id
 * @return error
 */
func (s *AuthUserService) DeleteAuthUser(id uint) error {
	var data models.AuthUser
	if err := s.DB.Where("id = ?", id).First(&data).Error; err != nil {
		return errors.New("数据不存在")
	}
	if data.GroupID == 0 {
		return errors.New("超级管理员不能删除")
	}
	err := s.DB.Delete(&data).Error
	if err != nil {
		return errors.New("删除失败")
	}
	return err
}

/**
 * @Description: 批量删除用户
 * @param id
 * @return error
 */
func (s *AuthUserService) DeleteAuthUsers(ids []string) error {
	for _, id := range ids {
		var data models.AuthUser
		if err := s.DB.Where("id = ?", id).First(&data).Error; err != nil {
			return errors.New("数据不存在")
		}
		if data.GroupID == 0 {
			return errors.New("超级管理员不能删除")
		}
		err := s.DB.Delete(&data).Error
		if err != nil {
			return errors.New("删除失败")
		}
	}
	return nil
}
